<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html><head><title>Programming in Lua : 13.2</title>
<link rel="stylesheet" type="text/css" href="pil.css">
</head>
<body>
<p class="warning">
<A HREF="contents.html"><IMG TITLE="Programming in Lua (first edition)" SRC="capa.jpg" ALT="" ALIGN="left"></A>This first edition was written for Lua 5.0. While still largely relevant for later versions, there are some differences.<BR>The third edition targets Lua 5.2 and is available at <A HREF="http://www.amazon.com/exec/obidos/ASIN/859037985X/theprogrammil3-20">Amazon</A> and other bookstores.<BR>By buying the book, you also help to <A HREF="../donations.html">support the Lua project</A>.
</p>
<table width="100%" class="nav">
<tr>
<td width="10%" align="left"><a href="13.1.html"><img border="0" src="left.png" alt="Previous"></a></td>
<td width="80%" align="center"><a href="contents.html"><font face="Helvetica,Arial,sanserif">
<font color="gray">Programming in </font><font color="blue"> Lua</font>
</font></a></td>
<td width="10%" align="right"><a href="13.3.html"><img border="0" src="right.png" alt="Next"></a></td>
</tr>
<tr>
<td width="10%" align="left"></td>
<td width="80%" align="center"><a href="contents.html#P2">Part II. Tables and Objects</a>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<a href="contents.html#13">Chapter 13. Metatables and Metamethods</a></td>
<td width="10%" align="right"></td></tr>
</table>
<hr/>
<p><h2>13.2 &ndash; Relational Metamethods</h2>

<p>Metatables also allow us to give meaning to the relational operators,
through the metamethods <code>__eq</code> (<em>equality</em>),
<code>__lt</code> (<em>less than</em>), and <code>__le</code> (<em>less or equal</em>).
There are no separate metamethods for the
other three relational operators,
as Lua translates <code>a ~= b</code> to <code>not (a == b)</code>,
<code>a > b</code> to <code>b &lt; a</code>, and <code>a >= b</code> to <code>b &lt;= a</code>.

<p>(Big parentheses:
Until Lua 4.0, all order operators were translated to a single one,
by translating <code>a &lt;= b</code> to <code>not (b &lt; a)</code>.
However, this translation is incorrect when we have a
<em>partial order</em>,
that is, when not all elements in our type are properly ordered.
For instance,
floating-point numbers are not totally ordered in most machines,
because of the value <em>Not a Number</em> (<em>NaN</em>).
According to the IEEE 754 standard,
currently adopted by virtually every hardware,
NaN represents undefined values, such as the result of <code>0/0</code>.
The standard specifies that any comparison that
involves NaN should result in false.
That means that <code>NaN &lt;= x</code> is always false,
but <code>x &lt; NaN</code> is also false.
That implies that the translation from <code>a &lt;= b</code> to <code>not (b &lt; a)</code>
is not valid in this case.)

<p>In our example with sets, we have a similar problem.
An obvious (and useful) meaning for <code>&lt;=</code>
in sets is set containment:
<code>a &lt;= b</code> means that <code>a</code> is a subset of <code>b</code>.
With that meaning,
again it is possible that both <code>a &lt;= b</code> and
<code>b &lt; a</code> are false;
therefore, we need separate implementations for
<code>__le</code> (<em>less or equal</em>) and <code>__lt</code> (<em>less than</em>):

<pre>
    Set.mt.__le = function (a,b)    -- set containment
      for k in pairs(a) do
        if not b[k] then return false end
      end
      return true
    end
    
    Set.mt.__lt = function (a,b)
      return a &lt;= b and not (b &lt;= a)
    end
</pre>
Finally, we can define set equality through set containment:
<pre>
    Set.mt.__eq = function (a,b)
      return a &lt;= b and b &lt;= a
    end
</pre>
After those definitions, we are now ready to compare sets:
<pre>
    s1 = Set.new{2, 4}
    s2 = Set.new{4, 10, 2}
    print(s1 &lt;= s2)       --> true
    print(s1 &lt; s2)        --> true
    print(s1 >= s1)       --> true
    print(s1 > s1)        --> false
    print(s1 == s2 * s1)  --> true
</pre>

<p>Unlike arithmetic metamethods,
relational metamethods do not support mixed types.
Their behavior for mixed types mimics the
common behavior of these operators in Lua.
If you try to compare a string with a number for order,
Lua raises an error.
Similarly, if you try to compare two objects with
different metamethods for order, Lua raises an error.

<p>An equality comparison never raises an error,
but if two objects have different metamethods,
the equality operation results in false,
without even calling any metamethod.
Again, this behavior mimics the common behavior of Lua,
which always classifies strings as different from numbers,
regardless of their values.
Lua calls the equality metamethod only when the two objects
being compared share this metamethod.

<hr/>
<table width="100%" class="nav">
<tr valign="top">
<td width="90%" align="left">
<small>
  Copyright &copy; 2003&ndash;2004 Roberto Ierusalimschy.  All rights reserved.
</small>
</td>
<td width="10%" align="right"><a href="13.3.html"><img border="0" src="right.png" alt="Next"></a></td>
</tr>
</table>


</body></html>

